﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using Omu.Awesome.Core;
using XPressify.Core;
using XPressify.Data.Helpers;

namespace XPressify.Data.CompliedQueries
{
    public class RelationshipCompiledQueries
    {
        

        public static Func<Repository, Guid, Guid,bool> AreFriends
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, bool>(
                    (context, firstUserId, secondUserId) => context.BaseObjects.OfType<Relationship>().Any(
                    rel =>
                    rel.RelationType == RelationshipType.FriendOf &&
                    ((rel.BaseSubject.Id == firstUserId && rel.BaseSubject2.Id == secondUserId) ||
                     (rel.BaseSubject.Id == secondUserId && rel.BaseSubject2.Id == firstUserId)) &&
                    rel.Status == RelationshipStatus.Confirmed)
                    );
            }
        }


        public static Func<Repository, Guid, Guid, bool> IsAdministrator
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, bool>(
                    (context, userId, subjectId) => context.BaseObjects.OfType<Relationship>().Any(
                        rel =>
                        rel.BaseSubject.Id == userId && rel.BaseSubject2.Id == subjectId &&
                        rel.Status == RelationshipStatus.Confirmed &&
                        rel.RelationType == RelationshipType.AdministratorOf)
                    );
            }
        }

        public static Func<Repository, Guid, Guid, bool> IsMember
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, bool>(
                    (context, userId, subjectId) => context.BaseObjects.OfType<Relationship>().Any(
                        rel =>
                        rel.BaseSubject.Id == userId && rel.BaseSubject2.Id == subjectId &&
                        rel.RelationType == RelationshipType.MemberOf && rel.Status == RelationshipStatus.Confirmed)
                    );
            }
        }

        public static Func<Repository, Guid, Relationship> GetRelationship
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Relationship>(
                    (context, relationshipId) => context.BaseObjects.OfType<Relationship>().SingleOrDefault(x => x.Id == relationshipId)
                    );
            }
        }

        public static Func<Repository, Guid, Guid, Relationship> GetMemberOfRelationship
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, Relationship>(
                    (context, userId, subjectId) => context.BaseObjects.OfType<Relationship>().SingleOrDefault(
                        rel =>
                        rel.BaseSubject.Id == userId && rel.BaseSubject2.Id == subjectId &&
                        rel.RelationType == RelationshipType.MemberOf && rel.Status == RelationshipStatus.Confirmed)
                    );
            }
        }

        public static Func<Repository, Guid, IEnumerable<Relationship>> GetAllRelationshipsOf
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, IEnumerable<Relationship>>(
                    (context, subjectId) => context.BaseObjects.OfType<Relationship>().Where(
                        x => x.BaseSubjectId == subjectId || x.BaseSubjectId2 == subjectId)
                    );
            }
        }

        public static Func<Repository, Guid, IEnumerable<Relationship>> GetBlockedRelationships
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, IEnumerable<Relationship>>(
                    (context, subjectId) => context.BaseObjects.OfType<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject.Id == subjectId || rel.BaseSubject2.Id == subjectId) &&
                    rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked)
                    );
            }
        }

        public static Func<Repository, Guid, Guid, Relationship> AnyMemberRelationship
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, Relationship>(
                    (context, userId, subjectId) => context.BaseObjects.OfType<Relationship>().SingleOrDefault(
                        rel =>
                        rel.BaseSubject.Id == userId && rel.BaseSubject2.Id == subjectId &&
                        rel.RelationType == RelationshipType.MemberOf)
                    );
            }
        }

        public static Func<Repository, Guid, Guid, bool> IsBlocked
        {
            get
            {
                return CompiledQuery.Compile<Repository, Guid, Guid, bool>(
                    (context, userId, userId2) => context.BaseObjects.OfType<Relationship>().Any(
                        rel =>
                        ((rel.BaseSubject.Id == userId && rel.BaseSubject2.Id == userId2) ||
                         (rel.BaseSubject2.Id == userId && rel.BaseSubject.Id == userId2)) &&
                        rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked)
                    );
            }
        }

    }
}